/**
 * 
* @author martin
 *
 */

import java.util.Random;

public class GameLogic extends EstablishGui {
	
	/**
	 * hraci
	 */
	private static Player actualPlayer;	
	private Player[] players = getGame().getPlayers();
	private static Figure[] positions;
	private static final int PATH_LEN = 2 * (Grid.gridSize - 4) + 2 * (Grid.gridSize - 6) - 1;
	private static final int TOTAL_DISTANCE = PATH_LEN + (Grid.gridSize - 4) / 2;
	
	private NewTurn turn;
	
	/**
	 * 
	 */
	public GameLogic() {
		super(true);		
		setActualPlayer( getGame().getPlayers()[0] );	
		
		int arrLength = Grid.gridSize;
		positions = new Figure[PATH_LEN];
	}

	
	public static Player getActualPlayer() {
		return actualPlayer;
	}
	
	public void setActualPlayer(Player newPlayer) {
		actualPlayer = newPlayer;
	}
	
	/**
	 * 
	 * @param actualTurn2 
	 * @return vraci Figure, ktera je vyhozena, jinak null
	 */
	
	public Figure moveFigure(NewTurn theTurn) {
		
		Figure figureOnPositionToMove = null;
		
		Figure theFigureToMove = getActualPlayer().getFigures()[0];
			int oldPosition = theFigureToMove.getPosition();			
			int toMove = theTurn.getNumberThrown();
			int toMoveFinal;
			
			if ( theFigureToMove.getIsOnBoard() )  {
				if ( oldPosition + toMove > PATH_LEN - 1 ) {
					toMoveFinal = oldPosition + toMove - PATH_LEN;
					
				}
				else {
					toMoveFinal = oldPosition + toMove;
				}
				
			}
			
			else {
				toMoveFinal = theFigureToMove.getStartingPos(); //pro nasazovani
			}			
			
			figureOnPositionToMove = positions[toMoveFinal];
			
			/*if ( theFigureToMove.getIsOnBoard() ) {
				performMove(theFigureToMove, figureOnPositionToMove, toMoveFinal, toMove, theTurn);
			}*/
			
			//Nasazeni figurky, pokud hodi 6, pak nastavi pozici na startovni podle atributu startPosition
			if ( !theFigureToMove.getIsOnBoard() && !theFigureToMove.isVictory() ) {
				if (toMove == 6) {
					positions[theFigureToMove.getStartingPos()] = theFigureToMove;
					performMove(theFigureToMove, figureOnPositionToMove, toMoveFinal, 0, theTurn);
					theFigureToMove.setIsOnBoard(true);
				}
			} else if (theFigureToMove.getIsOnBoard()) {
				performMove(theFigureToMove, figureOnPositionToMove, toMoveFinal, toMove, theTurn);
				
			}
		
		return theTurn.getThrownOutFigure();
	}
	
	public void throwFigureOut(Figure figureOnPositionToMove, NewTurn theTurn) {
		if (figureOnPositionToMove != null) {
			
			/*NewTurn theTurn = new NewTurn();*/
			
			//figurka stejneho hrace
			//if ( !figureOnPositionToMove.getColor().equals(theFigureToMove.getColor()) ) {
				//vratit figurku na pozici toMoveFinal do vychozi pozice
				theTurn.setThrownOutFigure(figureOnPositionToMove);
				figureOnPositionToMove.setDistanceGone(0);
				figureOnPositionToMove.setIsOnBoard(false);
				figureOnPositionToMove.setPosition( figureOnPositionToMove.getStartingPos() );
				
			//}
			
		}	
	}
	
	public void performMove(Figure theFigureToMove, Figure figureOnPositionToMove, int toMoveFinal, int toMove, NewTurn theTurn) {

		int distanceGone = theFigureToMove.getDistanceGone();
		int distanceToBe = distanceGone + toMove;
		
		//provede posun figurky pouze pokud je to v ramci jednoho kola
		if (distanceToBe < TOTAL_DISTANCE + 1) {
			positions[theFigureToMove.getPosition()] = null;
			theFigureToMove.setPosition( toMoveFinal ); //nastavi pozici
			theFigureToMove.setDistanceGone( distanceToBe );
			positions[toMoveFinal] = theFigureToMove;
			throwFigureOut(figureOnPositionToMove, theTurn);
		}
		if (distanceToBe == TOTAL_DISTANCE + 1) {
			//v domecku uz nevyhazuje, proto se nevola throwFigureOut
			positions[theFigureToMove.getPosition()] = null;
			theFigureToMove.setPosition( theFigureToMove.getFinalPosition() ); //nastavi cilovou pozici
			theFigureToMove.setIsOnBoard(false);
			theFigureToMove.setIsVictory(true);
			
			boolean finished = true;
			Figure[] figures = actualPlayer.getFigures();
			int i = 0;
			while (finished) {
				finished = figures[i].isVictory();
				i++;
			}
			
			if (finished) {
				actualPlayer.setFinished(true);
			}
			
			if ( gameFinished() ) {//overit jestli skoncila hra:
				getGame().setGameFinished(true);
			}
		}
	}
	
	public boolean gameFinished() {
		boolean finished = true;
		for ( Player pl : players ) {
			finished = finished && pl.isFinished();
		}
		return finished;
	}
	
	public static int generateRandomNumber() {
		return new Random().nextInt(6) + 1;
	}
	
	public void performTurn() {
		turn = new NewTurn();
		Figure actualPlayersFigure = getActualPlayer().getFigures()[0]; //na tomto miste se voli figurka
		Player actualPlayer = getActualPlayer();
		
		
		
		//pokud figurka uz neni v domecku
		if ( !actualPlayersFigure.isVictory() ) {
			int numberThrown = 0;
			int newTurnNr = turn.getTurnNumber(); //zjisti cislo kola
			newTurnNr ++;
			turn.setTurnNumber( newTurnNr ); //nastavi nove cislo kola
			
			
			if (!actualPlayer.isInGame() && !actualPlayer.isFinished() ) { //... nasazuje, ma zezacatku tri pokusy 
				enterTheGame( getActualPlayer() );
			}
			
			if ( actualPlayer.isInGame() ) {
				numberThrown = generateRandomNumber(); //generuje random
				turn.setNumberThrown( numberThrown ); 				
			}
			
			//TODO moveFigure se navaze na event - vyber figurky 
			int oldPosition = actualPlayersFigure.getPosition(); 
			Figure figureToBeKilled = moveFigure(turn); //provede zmenu pozice ze stavajici na novou (stavajici + random viz ^^)
			
			//tady se predaji potrebne udaje na GUI, coz je: hod kostkou, puvodni pozice, objekt figurky
			if ( (actualPlayersFigure.getIsOnBoard() || actualPlayersFigure.isVictory()) && isUseGui() ) {
				if (figureToBeKilled == null) 
					getGui().redrawFigure(numberThrown, oldPosition, actualPlayersFigure);
				else 
					getGui().redrawFigure(numberThrown, oldPosition, actualPlayersFigure, figureToBeKilled);
			}
		}
		
		//TODO stridani jen mezi aktivnimi hraci
		/**
		 * moznosti
		 * a) rekurzivni metoda, nebo while cyklus, ktery vybere dalsiho hrace v poradi na zaklade atributu 
		 * b) novy ArrayList aktivnich hracu, pri ukonceni hry lze hrace odstranit, znamenalo by to taky, ze by se dal odstranit atribut a overovani, 
		 * zda je hrac ve hre by se provadelo pres contains()
		 * 
		 */
		
		int newPlayerID = getActualPlayer().getID() + 1;
		setActualPlayer( players[newPlayerID % 4] ); //zmeni hrace, MODULO 4 zajisti cyklus 
	}

	
	public void enterTheGame(Player actualPlayer) {
		
		int numberThrown = generateRandomNumber();
		//TODO nova metoda preda jen hod kostkou na GUI
		
		if ( numberThrown == 6 ) { 
			actualPlayer.setInGame(true);
		}
		else if (turn.getNumberOfTries() > 0) {
			turn.setNumberOfTries(turn.getNumberOfTries() - 1);
			enterTheGame(actualPlayer);
		}
		
	}
	
	public void simulateTurn(int n) {
		
		for (int i = 0; i < n; i++) {
			performTurn();
		}	
	}
	
	public String toString() {
		return actualPlayer + "; " + getActualPlayer().getFigures();
	}


	/**
	 * @return the pathLen
	 */
	public static int getPathLen() {
		return PATH_LEN;
	}

}